MB.createAd = {};
MB.createAd.modules = ['copy', 'adText', 'images', 'channels', 'targeting', 'preview', 'submit'];
MB.createAd.minPremium = null;
MB.createAd.channels = function() {
  var modalDialog = null;
  var allBidsDirty = false;
  var imagePremiumDirty = false;

  return {
    init: function() {
      Ext.get('channels_swizzle').on('click', function(e, el) {
        e.preventDefault();
        this.toggleChannels(!Ext.get('all_channels').isDisplayed());
      }, this);
      Ext.get('simplify_button').on('click', function(e, el) {
        e.preventDefault();
        this.toggleChannels(!Ext.get('all_channels').isDisplayed());
      }, this);

      Ext.select('#all_channels input').on({
        'change': this.getReview,
        'keyup': this.getReview,
        scope: this
      });

      var all_channel_text_bid_change_func = function(e, el) {
        allBidsDirty = true;
        this.getReview();
      }
      Ext.get('all_channel_text_bid').on({
        'change': all_channel_text_bid_change_func,
        'keyup': all_channel_text_bid_change_func,
        scope: this
      });

      Ext.get('all_total_bid').on('click', this.displayUpdateDialog, this, {stopEvent: true});

      var setInputState = function(e, el) {
        var inputbox = Ext.get('channel_bid_' + el.id.split('_')[1]);
        inputbox.dom.disabled = !el.checked;

        if(el.checked && inputbox.getValue().replace(/^\s\s*/, '').replace(/\s\s*$/, '') == '') { // fill w/ max from other channels bid
          var bids = [];
          var inputs = Ext.query('input[id^=channel_bid_]');
          for(var i = 0; i < inputs.length; i++)  {
            if(!inputs[i].disabled && !isNaN(parseFloat(inputs[i].value))) bids.push(parseFloat(inputs[i].value));
          }
          inputbox.dom.value = MB.format(Array.max(bids), {grp_sep: false});
        }
      }

     Ext.select('.channelCheckbox').on('change', setInputState);

      var buttons = [];
      var cancelHandler = function() {
        MB.createAd.channels.modalDialog.hide();
      }
      var saveHandler = function() {
        var value = parseFloat(Ext.get('modalInput').dom.value);
        if (isNaN(value) || value < MB.createAd.minPremium) {
          Ext.get('minPremiumSpan').dom.innerHTML = MB.format(MB.createAd.minPremium);
          Ext.get('modalInput').addClass('wrong');
          Ext.get('modalDialogError').setDisplayed('block');
        } else {
          Ext.get('modalInput').removeClass('wrong');
          Ext.get('modalDialogError').setDisplayed('none');
          Ext.get('image_bid').dom.value = Ext.get('modalInput').getValue();
          imagePremiumDirty = true;
          MB.createAd.channels.getReview();
          MB.createAd.channels.modalDialog.hide();
        }
      }
      var localUpdater = function() {
        var value = parseFloat(Ext.get('modalInput').dom.value);
        if(value > 0.00) {
          minWithImage = parseFloat(Ext.get('modal_min').getValue()) + value;
          maxWithImage = parseFloat(Ext.get('modal_max').getValue()) + value;
          if(minWithImage == maxWithImage) {
            Ext.get('modalTotal').update(minWithImage.toFixed(2));
          } else {
            Ext.get('modalTotal').update(minWithImage.toFixed(2) + ' - ' + maxWithImage.toFixed(2));
          }
        }
      }

      Ext.get('modalInput').on({
          'change': localUpdater,
          'keyup':  localUpdater
      });

      buttons[0] = {text: _('Set New Bid'), listeners: {'click': saveHandler}};
      buttons[1] = {text: _('Cancel'), listeners: {'click': cancelHandler}};

      var config = {draggable: false,
                    header: false,
                    modal: true,
                    resizable: false,
                    width: 300,
                    height: 375,
                    buttons: buttons,
                    title: _('Text & Image'),
                    body: Ext.get('modalDialogContent'),
                    id: 'modalBox',
                    closeAction: 'hide'
                   };
      this.modalDialog = new Ext.Window(config);
      if(ad_params) {
        var cbs = Ext.query('.channelCheckbox');
        Ext.each(cbs, function(item) {
          item.checked = false;
        }, this);
        Ext.each(Ext.query('.channelInput'), function(item) {
          item.disabled = true;
        }, this);

        allBidsDirty = true;
        // determine if channel bids are the same
        var cbid = false;
        var allc = true;
        for(var i in ad_params.channels) {
          var b = ad_params.channels[i];
          Ext.get('channel_bid_' + i).dom.value = MB.format(b, {grp_sep: false});
          Ext.get('channel_bid_' + i).dom.disabled = false;
          Ext.get('checkbox_' + i).dom.checked = true;
          if(cbid === false) {
            cbid = b;
          }
          else if(b != cbid) {
            allc = false;
          }
        }
        if(ad_params.banner_premium) {
          imagePremiumDirty = true;
          Ext.get('image_bid').dom.value = MB.format(ad_params.banner_premium, {grp_sep: false});
        }

        // if all checkboxes are checked and all bids are the same don't show the channels div
        Ext.each(cbs, function(item) {
          if(item.checked == false) {
            allc = false;
          }
        }, this);

        if(!allc) {
          this.toggleChannels(true, true);
        } else {
          Ext.get('all_channel_text_bid').dom.value = MB.format(cbid, {grp_sep: false});
        }
      }

      Ext.each(Ext.query('.channelCheckbox'), function(item) {
        setInputState(null, item);
      }, this);

      MB.createAd.channels.getReview();
    },
    toggleChannels: function(show, keep) {
      var keep_bids = keep || false;

      var all = Ext.get('all_channels');
      if(!show) {
        Ext.get('dollarSign').setDisplayed(true);
        Ext.get('all_channel_text_bid').setDisplayed(true);
        Ext.get('channel_bid_range').setDisplayed('none');
        var bids = [0];
        var pause = false;
        var alreadyLit = [];
        Ext.each(Ext.query('input[id^=channel_bid_]', 'all_channels'), function(item) {
          var checkbox = Ext.get('checkbox_' + item.id.split('_')[2]);
          if (!checkbox.dom.checked) {
            pause = true;
            checkbox.dom.checked = true;
            item.disabled = false;
            Ext.get(item).parent('td').highlight();
            alreadyLit[item.id.split('_')[2]] = true;
          }

          if(!isNaN(parseFloat(item.value))) bids.push(item.value);
        }, this);
        if(!keep_bids) {
          var topbid = MB.format(Array.max(bids), {grp_sep: false});
          Ext.get('all_channel_text_bid').setDisplayed(true).dom.value = topbid;
          Ext.each(Ext.query('input[id^=channel_bid_]', 'all_channels'), function(item) {
            if (parseFloat(item.value) != parseFloat(topbid) || isNaN(parseFloat(item.value))) {
              pause = true;
              item.value = topbid;
              if (!alreadyLit[item.id.split('_')[2]]) {
                Ext.get(item).parent('td').highlight();
              }
            }
          }, this);
        }
        Ext.get('channels_swizzle').setDisplayed('block');
        Ext.get('simplify_button').setDisplayed('none');
        if (pause) {
          all.pause(1.5);
        }
        if(Ext.isIE6) (function() { all.setDisplayed('none'); }).defer(1500);
        else all.slideOut('t', { useDisplay: true});

      }
      else {
        if(Ext.isIE6) all.setDisplayed('block');
        else all.slideIn('t', { useDisplay: true });
        Ext.get('dollarSign').setDisplayed('none');
        Ext.get('all_channel_text_bid').setDisplayed('none');
        Ext.get('channel_bid_range').setDisplayed(true);
        var actbid = (isNaN(parseFloat(Ext.get('all_channel_text_bid').getValue())) ? 0 : Ext.get('all_channel_text_bid').getValue());
        if(!keep_bids) {
          Ext.each(Ext.query('input[id^=channel_bid_]', 'all_channels'), function(item) {
            item.value = actbid;
          }, this);
        }
        Ext.get('simplify_button').setDisplayed('block');
        Ext.get('channels_swizzle').setDisplayed('none');
      }
      MB.createAd.channels.getReview();
    },
    isAllInputDirty: function() {
      return allBidsDirty;
    },
    isImagePremiumDirty: function() {
      return imagePremiumDirty;
    },
    displayUpdateDialog: function() {
      Ext.get('modalInput').removeClass('wrong');
      Ext.get('modalDialogContent').setDisplayed('block');
      Ext.get('modalInput').dom.value = parseFloat(Ext.get('image_bid').getValue()).toFixed(2);
      this.modalDialog.show();
    },
    getValues: function() {
      var v = {};

      if(Ext.get('all_channels').isDisplayed()) { // specific channels
        v.channels = {};
        Ext.each(Ext.query('#all_channels input'), function(item, i, all) {
          if(item.name == 'channels[]' && item.checked) {
            v.channels[item.value] = Ext.get('channel_bid_' + item.value).dom.value;
          }
        }, this);
      }
      else {
        v.all_channels_bid  = Ext.get('all_channel_text_bid').dom.value;
      }

      v.image_bid = Ext.get('image_bid').getValue();

      return v;
    },
    getReview: function() {
      var v = this.getValues();
      var usedChannels;

      if(v.all_channels_bid) {
        var min = (isNaN(parseFloat(v.all_channels_bid)) ? 0 : parseFloat(v.all_channels_bid));
        var max = min;
        usedChannels = false;
      }
      else {
        usedChannels = true;
        var bids = [];
        for(var i in v.channels) {
          if(!isNaN(parseFloat(v.channels[i]))) bids.push(parseFloat(v.channels[i]));
        }
        if(bids.length == 0) {
          var min = 0;
          var max = 0;
        }
        else {
          var min = parseFloat(Array.min(bids));
          var max = parseFloat(Array.max(bids));
        }
      }

      var image = parseFloat(v.image_bid);
      var withImageMin = MB.format(min + image);
      var withImageMax = MB.format(max + image);
      Ext.get('text_bid').update((min == max) ? "$" + MB.format(min) : "$" + MB.format(min) + ' - $' + MB.format(max));
      Ext.get('channel_bid_range').update((min == max) ? "$" + MB.format(min) : "$" + MB.format(min) + ' - $' + MB.format(max));
      Ext.get('modal_text_bid').update((min == max) ? MB.format(min) : MB.format(min) + ' - ' + MB.format(max));
      Ext.get('modalTotal').update((min == max) ? '$' + withImageMin : '$' + withImageMin + ' - $' + withImageMax );
      Ext.get('all_total_bid').update((min == max) ? '$' + withImageMin : '$' + withImageMin + ' - $' + withImageMax );
      Ext.get('text_image_bid').update((min == max) ? '$' + withImageMin : '$' + withImageMin + ' - $' + withImageMax );
      Ext.get('modal_min').dom.value = min;
      Ext.get('modal_max').dom.value = max;
    }
  };
}();

MB.createAd.targeting = function() {
  var manfTree = null;
  var countryTree = null;
  var bidGuideUpdateCall = null;
  var bidGuideUpdateAjaxCall = null;
  var reviewUpdateCall = null;
  var targetingTpl = function(v) {
    var t = '<p style="float: right;"><a href="#" onclick="return MB.createAd.targeting.showDetails()">' + _('Details') + '</a></p>';
    if(v.countries[0] == 'any_reg') {
      t += '<p><b>' + _('All Regions') + '</b></p>';
    }
    else if(v.countries[0] == 'CCUS') {
      t += '<p><b>' + _('United States') + '</b></p>';
    }
    else if(v.countries[0] == 'CCGB') {
      t += '<p><b>' + _('United Kingdom') + '</b></p>';
    }
    else {
      if(v.real_carriers.length) {
        t += '<p>' + _('<b>%1</b> Carrier', '<b>%1</b> Carriers', v.real_carriers.length) + _(' in ');
      }
      t += _('<b>%1</b> Country', '<b>%1</b> Countries', v.real_countries.length);
      t += ' (' + _('<b>%1</b> Region', '<b>%1</b> Regions', v.real_regions.length) + ')</p>';
    }
    if(v.devices[0] == 'any_dev') {
      // assume simple manufacturer targeting
      if(v.manfs[0] == 'any_manf') {
        t += '<p><b>' + _('All Manufacturers') + '</b></p>';
      }
      else {
        t += '<p>' + _('<b>%1</b> Manufacturer', '<b>%1</b> Manufacturers', v.manfs.length) + '</p>';
      }
      if(v.platform[0] == 'any_plat') {
        t += '<p><b>' + _('All Platforms') + '</b></p>';
      }
      else {
        t += '<p>' + _('<b>%1</b> Platform', '<b>%1</b> Platforms', v.platform.length) + '</p>';
      }
      if(v.new_cap[0] == 'any_cap') {
        t += '<p><b>' + _('Any Capabilities') + '</b></p>';
      }
      else {
        t += '<p>' + _('<b>%1</b> Required Capability', '<b>%1</b> Required Capabilities', v.new_cap.length) + '</p>';
      }
    }
    else {
      t += '<p>' + _('<b>%1</b> Targeted Device', '<b>%1</b> Targeted Devices', v.devices.length) + '</p>';
    }
    return t;
  };
  var targetingDetailsDialogTpl = null;
  var currentReviewArray = null;
  var targetDevices = {};
  var device_search_grid = null;
  var device_search_expanded_row = null;
  var selected_devices;
  var device_selections_sel_model = null;
  var search_results;
  var device_search_checked;
  var device_search_grid_height;
  if(Ext.isIE) {  // FIXME: hackery!
    var initial_string = _('Example:') + '\r\nNokia N95\r\nBlackberry 8300\r\nMotorola Razr';
  }
  else {
    var initial_string = _('Example:') + '\nNokia N95\nBlackberry 8300\nMotorola Razr';
  }


  return {
    init: function() {
      // override default double clicking Ext behavior (was unable to stop expand/collapse event for double clicking
      Ext.override(Ext.tree.TreeNodeUI, {
        onDblClick : function(e) {
          e.preventDefault();
          if(this.disabled) {
              return;
          }
          if(this.checkbox) {
              this.toggleCheck();
          }
          if (this.fireEvent('dblclick', this.node, e) !== false) {
            if(!this.animating && this.node.hasChildNodes()) {
              this.node.toggle();
            }
          }
        }
      });


      var specific_out = function(e, el) {
        if(e) e.stopPropagation();
        if(el && el.checked) {
          var d = Ext.get(el.id.match(/(.*)_all/)[1] + '_specific_div');
          if(d.isDisplayed()) {
            if(Ext.isIE6) {
              d.setDisplayed('none');
            }
            else {
              MB.createAd.state.startSpecific();
              d.slideOut(null, {useDisplay: true,
                                callback: MB.createAd.state.stopSpecific});
            }
          }
        }
      }

      if(ad_params && ad_params.targeting) {
        MB.createAd.targeting.load_saved_ad(ad_params.targeting);
      } else {
        MB.createAd.targeting.switch_device_targeting(null, null);
      }

      Ext.get('cap_targeting_all').on('click', specific_out);
      Ext.get('platform_targeting_all').on('click', specific_out);

      Ext.get('cap_targeting_specific').on('click', this.specific_in);
      Ext.get('platform_targeting_specific').on('click', this.specific_in);

      Ext.get('device_targeting_search').on('focus', MB.createAd.targeting.deviceSearchSampleText);
      Ext.get('device_targeting_search').on('blur', MB.createAd.targeting.deviceSearchSampleText);

      Ext.get('device_targeting_del_selection').on('click', MB.createAd.targeting.deleteSelectedHandsets);
      Ext.get('device_targeting_search_button').on('click', MB.createAd.targeting.openDevicePopup);
      Ext.get('device_targeting_popup_addbtn').on('click', MB.createAd.targeting.hideDevicePopup);
      Ext.get('device_targeting_popup_cancelbtn').on('click', MB.createAd.targeting.hideDevicePopup);

      Ext.select('#targeting_module input').on('click', this.triggerUpdate, this);

      Ext.get('device_targeting_search_grid').on('click', MB.createAd.targeting.gridClickHandler);

      Ext.select('#targeting_options input').on('click', this.switch_country_targeting);
      // Ext.get('targeting_us').on('click', this.switch_country_targeting);

      this.switch_country_targeting(null, null);

      Ext.get('device_targeting_all').on('click', MB.createAd.targeting.switch_device_targeting);
      Ext.get('device_targeting_bymanf').on('click', MB.createAd.targeting.switch_device_targeting);
      Ext.get('device_targeting_bysearch').on('click', MB.createAd.targeting.switch_device_targeting);

//       MB.createAd.targeting.switch_device_targeting(null, null);

      if(Ext.get('cap_targeting_specific').dom.checked) this.specific_in(null, Ext.get('cap_targeting_specific').dom);
      if(Ext.get('platform_targeting_specific').dom.checked) this.specific_in(null, Ext.get('platform_targeting_specific').dom);

      if(Ext.get('demo_targeting')) {
        Ext.get('age_targeting_all').on('click', specific_out);
        Ext.get('age_targeting_specific').on('click', this.specific_in);
        if(Ext.get('age_targeting_specific').dom.checked) this.specific_in(null, Ext.get('age_targeting_specific').dom);
      }

    if(document.location.href.match(/android$/)) {
      MB.createAd.targeting.switch_device_targeting(null, 'device_targeting_bymanf');
      Ext.getDom('platform_targeting_specific').checked = true;
      MB.createAd.targeting.specific_in(null, Ext.getDom('platform_targeting_specific'));
      Ext.each(Ext.query('#platform_targeting_specific_div input[value!=android]'), function(i) {
          i.checked = false;
      });
    }

      MB.createAd.state.stopCheckboxes();
    }, // end init
    specific_in: function(e, el) {
      if(e) e.stopPropagation();
      if(el && el.checked) {
        var d = Ext.get(el.id + '_div');
        if(!d.isDisplayed()) {
          if(Ext.isIE6) {
            d.setDisplayed('block');
          }
          else {
            MB.createAd.state.startSpecific();
            d.slideIn(null,{useDisplay: true,
                            callback: MB.createAd.state.stopSpecific});
          }
        }
      }
    },
    load_saved_ad: function(apt) {
      if(!apt.any_dev) {
        for(var handset_id in apt.devices) {
          targetDevices[handset_id] = apt.devices[handset_id];
        }
        MB.createAd.targeting.switch_device_targeting(null, 'device_targeting_bysearch');
      }
      else if(apt.new_manfs.length == 0 &&
              apt.new_platform.length == 0 &&
              apt.new_cap.length == 0) {
        MB.createAd.targeting.switch_device_targeting(null, 'device_targeting_all');
      }
      else {
        MB.createAd.targeting.switch_device_targeting(null, 'device_targeting_bymanf');
        if(apt.new_platform.length > 0) {
          Ext.get('platform_targeting_specific').dom.checked = true;
          Ext.each(Ext.query('#platform_targeting_specific_div input'), function(item) { item.checked = false; });
          for(var wp = 0, l = apt.new_platform.length; wp < l; wp++) {
            Ext.get(apt.new_platform[wp] + '_targeting').dom.checked = true;
          }
        }
        if(apt.new_cap.length > 0) {
          Ext.get('cap_targeting_specific').dom.checked = true;
          for(var wp = 0, l = apt.new_cap.length; wp < l; wp++) {
            Ext.get(apt.new_cap[wp] + '_targeting').dom.checked = true;
          }
        }
      }

      if(apt.age.length > 0 &&
          Ext.get('age_targeting_div')) {
        Ext.get('age_targeting_specific').dom.checked = true;
        Ext.each(apt.age, function(item) {
          var e = Ext.get('age_targeting_'+item);
          if(e){ e.dom.checked = true; }
        });
      }

      if(apt.gender != 'any_gender' &&
          Ext.get('gender_targeting_div')) {
        if(apt.gender == 'f') {
          Ext.get('gender_targeting_female').dom.checked = true;
        }
        else {
          Ext.get('gender_targeting_male').dom.checked = true;
        }
      }

      if(Ext.get('msisdn_targeting')) {
        Ext.get('msisdn_on').dom.checked = apt.new_msisdn;
      }
    },

    switch_country_targeting: function(e, el) {
      if(e) e.stopPropagation();

      if(!MB.createAd.state.startCountry()) {
        if(e) e.preventDefault();
        return false;
      }

      if(!el) {
        Ext.each( Ext.query('#targeting_options input'),
                  function(item) {
                    if(item.checked) { el = item; }
                  });
      }

      if(Ext.get(el).is('div.targeting_option')) {
        var target = Ext.get(el);
      }
      else {
        var target = Ext.get(el).findParentNode('div.targeting_option', null, true);
      }

      if(target.id.match(/ron/)) {
        // disable device targeting and reset if selected
        Ext.get('device_targeting_bysearch').dom.disabled = true;
        Ext.get('device_targeting_bysearch_label').addClass('targeting_disabled');
        Ext.get('device_targeting_warning').setDisplayed(true);
        if(Ext.get('device_targeting_bysearch').dom.checked) {
          MB.createAd.targeting.switch_device_targeting(null, 'device_targeting_all');
        }
      } else {
        Ext.get('device_targeting_bysearch').dom.disabled = false;
        Ext.get('device_targeting_bysearch_label').removeClass('targeting_disabled');
        Ext.get('device_targeting_warning').setDisplayed(false);
      }

      var ct = Ext.get('custom_targeting');
      if(target.id.match(/custom/)) {
        MB.createAd.targeting.showCountryTree();
        if(ct.isDisplayed() || Ext.isIE) {
          ct.setDisplayed(true);
          MB.createAd.state.stopCountry();
        }
        else {
          ct.slideIn(null, {
            useDisplay: true,
            callback: MB.createAd.state.stopCountry
          });
        }
        target.addClass('targeting_selected');
      }
      else {
        Ext.get('targeting_div_custom').removeClass('targeting_selected');
        if(!ct.isDisplayed() || Ext.isIE6) {  // slide only if Custom was selected
          ct.setDisplayed(false);
          MB.createAd.state.stopCountry();
        }
        else {
          ct.slideOut(null, {
            useDisplay: true,
            callback: MB.createAd.state.stopCountry
          });
        }
      }
    },

    switch_device_targeting: function(e, el) {
      if(e) e.stopPropagation();
      if(!MB.createAd.state.startDevice()) {
        if(e) e.preventDefault();
        return false;
      }

      if(!el) {
        var el = {};
        if(Ext.get('device_targeting_all').dom.checked) {
          el.id = 'device_targeting_all';
        }
        if(Ext.get('device_targeting_bymanf').dom.checked) {
          el.id = 'device_targeting_bymanf';
        }
        if(Ext.get('device_targeting_bysearch').dom.checked) {
          el.id = 'device_targeting_bysearch';
        }
      }
      else {
        el = Ext.get(el);
        el.dom.checked = true; // TODO: check against create_ad.php
      }

      var items_to_hide = ['device_targeting_bymanf','device_targeting_bysearch'];
      var item_to_show = '';
      Ext.select('#device_targeting .targeting_option').removeClass('targeting_selected');

      switch(el.id) {
        case 'device_targeting_bymanf':
          items_to_hide = ['device_targeting_bysearch'];
          item_to_show = 'device_targeting_bymanf';
          Ext.get('targeting_div_device_bymanf').addClass('targeting_selected');
          break;
        case 'device_targeting_bysearch':
          items_to_hide = ['device_targeting_bymanf'];
          item_to_show = 'device_targeting_bysearch';
          Ext.get('targeting_div_device_bysearch').addClass('targeting_selected');
          break;
      }

      MB.createAd.state.startDevice();
      Ext.each(items_to_hide, function(el) {
        var d = Ext.get(el+'_div');
        if(d.isDisplayed()) {
          if(Ext.isIE6) d.setDisplayed('none');
          else d.slideOut(null, {useDisplay: true});
        }
      });

      var d = Ext.get(item_to_show+'_div');
      if(d && !d.isDisplayed()) {
        if(Ext.isIE) {
          d.setDisplayed('block');
          MB.createAd.state.stopDevice();
        }
        else {
            d.slideIn(null,{useDisplay: true,
                            callback: MB.createAd.state.stopDevice});
        }
      } else {
        MB.createAd.state.stopDevice();
      }

      // in IE this can't be done before displaying the block
      switch(el.id) {
        case 'device_targeting_bymanf':
          if(manfTree == null) MB.createAd.targeting.createManufacturerTree();
          break;
        case 'device_targeting_bysearch':
          MB.createAd.targeting.deviceSearchSampleText(null, 'device_targeting_search');
          MB.createAd.targeting.selectedItemsGrid();  // TODO: check for double-setting
          break;
      }

    },

    deviceSearchSampleText: function(e, el) {
      if(e) {
        e.stopPropagation();
        el = e.target || e.srcElement;
      }
      el = Ext.get(el);
      if(!e || el.dom.value == '') {
        el.addClass('device_targeting_default_search');
        el.dom.value = initial_string;
      } else if(e && el.dom.value == initial_string) {
        el.removeClass('device_targeting_default_search');
        el.dom.value = '';
      }
    },

    openDevicePopup: function(e,el) {
      if(e) e.stopEvent();
      var search_terms = Ext.get('device_targeting_search').getValue();
      if(search_terms == initial_string) { return false; }
      if(!MB.createAd.targeting.validateDeviceSearch(search_terms)) {
        Ext.get('device_search_error').setDisplayed(true);
        return false;
      } else {
        Ext.get('device_search_error').setDisplayed(false);
      }

      Ext.Ajax.request({
        url: MB.constant.base_control + 'ajax/targeting/wurfl_search',
        success: MB.createAd.targeting.devicePopupCallback,
        params: { 'search_terms': search_terms }
      });
      Ext.get('device_search_spinner').setDisplayed(true);
      Ext.get('device_targeting_search_button').dom.disabled = true;
      MB.createAd.targeting.resetDevicePopup();
    },

    resetDevicePopup: function() {
      device_search_grid_height = 435;
      device_search_expanded_row = null;

      Ext.get('device_targeting_popup_iphone').setDisplayed(false);
      Ext.get('device_targeting_popup_unmatched').setDisplayed(false);
    },

    validateDeviceSearch: function(search_string) {
      var search_lines = search_string.split(/[\r\n]+/);
      if(search_lines.length > 51) { return false; }

      for(var i = 0; i < search_lines.length; i ++) {
        if(search_lines[i] == '') { continue; }

        // each line should be "manufacturer<space>model"
        if(search_lines[i].indexOf(' ') == -1) {
          return false;
        }
      }

      return true;
    },

    devicePopupCallback: function(response) {
      search_results = Ext.util.JSON.decode(response.responseText);

      if(search_results.error) {
        Ext.get('device_search_spinner').setDisplayed(false);
        Ext.get('device_targeting_search_button').dom.disabled = false;
        alert(search_results.error);
        return false;
      }

      MB.createAd.targeting.updateResultCounts(search_results.counts);

      if(search_results.unmatched.length > 0) {
        Ext.get('device_targeting_popup_unmatched_list').update(
                // TODO: asterisked single words?
                search_results.unmatched.join(', ')
                );
        Ext.get('device_targeting_popup_unmatched').setDisplayed(true);
        device_search_grid_height -= 75;
      }

      device_search_checked = [];
      for(var i = 0; i < search_results.display_rows.length; i ++) {
        device_search_checked[i] = [];
      }

      Ext.getBody().mask();
      MB.createAd.targeting.deviceSearchGrid();
      Ext.get('device_targeting_popup').fadeIn();
      Ext.get('device_targeting_popup').center();
    },

    updateResultCounts: function(counts) {
      var count_string = '';
      if(counts['multi']) {
        count_string += '<li>' + _('%1 partial match requiring review', '%1 partial matches requiring review', counts['multi']) + '</li>';
      }
      if(counts['exact']) {
        count_string += '<li>' + _('%1 exact match', '%1 exact matches', counts['exact']) + '</li>';
      }
      if(counts['none']) {
        count_string += '<li>' + _('%1 unmatched search', '%1 unmatched searches', counts['none']) + '</li>';
      }
      if(counts['iphone']) {
        count_string += '<li id="device_search_iphone_match">' + _('iPhone match. See note above.') + '</li>';
      }
      Ext.get('device_targeting_popup_counts').update(count_string);
      if(counts['iphone']) {
        Ext.get('device_targeting_popup_iphone').setDisplayed(true);
        device_search_grid_height -= 80;
      }
    },

    deviceSearchGrid: function() {
      Ext.get('device_targeting_search_grid').update('');   // TODO: clear more nicely?

      var device_search_sel_model = new Ext.grid.RowSelectionModel({});
      var device_search_data_store = new Ext.data.Store({
        proxy: new Ext.data.MemoryProxy(search_results.display_rows),
        reader: new Ext.data.ArrayReader({ id: 'handset_id' }, [
          { name: 'handset_id', type: 'string' },
          { name: 'search_term', type: 'string' },
          { name: 'manufacturer', type: 'string' },
          { name: 'model', type: 'string' },
          { name: 'market_name', type: 'string' }
        ])
      });
      device_search_data_store.load();

      var twizzle_renderer = function(value, metadata, record, row_index, col_index, data_obj) {
        // TODO: get this array from datastore?
        var match_count = search_results.display_rows[row_index][5].length;
        if(match_count > 1) {
          var twizzle_class = 'device_search_twizzle';
          if(device_search_expanded_row !== null
              && device_search_expanded_row == row_index) {
            twizzle_class += ' device_search_twizzle_open';
          }
          return String.format(
                  '<a href="#" '
                  + 'class="{1}"'
                  + ' id="device_search_twizzle_' + row_index
                  + '">{0} ' + _('matches') + '</a>',
                  match_count, twizzle_class);
        }
        else {
          return String.format('{0}', value);
        }
      }

      var first_column_renderer = function(value, metadata, record, row_index, col_index, data_obj) {
        var match_count = search_results.display_rows[row_index][5].length;
        var checked_status = 'ext-cb-unchecked';
        var check_type = 'device_search_sel_exact';
        if(match_count > 1) {
          check_type = 'device_search_sel_multi';
          if(device_search_checked[row_index].length > 0) {
            checked_status = 'ext-cb-checked';
            if(device_search_checked[row_index].length != match_count) {
              checked_status = 'ext-cb-partial';
            }
          }
        }
        else {
          if(device_search_checked[row_index].length > 0) {
            checked_status = 'ext-cb-checked';
          }
        }
        return String.format(
               '<span class="{3} device_targeting_cb ext-tree-cb {2}" id="device_sel_{1}"></span> <span class="{3}" id="device_lbl_{1}">{0}</span>',
               value, row_index, checked_status, check_type);
      }

      device_search_grid = new Ext.grid.GridPanel({
          el: 'device_targeting_search_grid',
          selModel: device_search_sel_model,
          width: 550,
          height: device_search_grid_height,
          title: _('Handset Search Results'),
          header: false,
          stripeRows: true,
          store: device_search_data_store,
          colModel: new Ext.grid.ColumnModel( [
            { header: _('Search Term'),
              dataIndex: 'search_term',
              width: 130,
              renderer: first_column_renderer,
              menuDisabled: true,
              sortable: true },
            { header: _('Brand Name'),
              dataIndex: 'manufacturer',
              width: 120,
              menuDisabled: true,
              sortable: true },
            { header: _('Model Name'),
              dataIndex: 'model',
              width: 153,
              renderer: twizzle_renderer,
              menuDisabled: true },
            { header: _('Marketing Name'),
              dataIndex: 'market_name',
              width: 145,
              menuDisabled: true }
          ] ),
          viewConfig: {
            forceFit: true,
            enableRowBody: true,
            getRowClass: function(record, row_index, row_params, store){
              if(device_search_expanded_row == row_index) {
                var left_col = '';
                var right_col = '';
                var child_match_row = new Ext.Template(
                        '<div class="device_search_partial_left">',
                        '<span id="device_sel_{row_index}_{item_index}" class="device_search_sel_partial device_targeting_cb ext-tree-cb {checked_status}"></span> ',
                        '<span class="device_search_sel_partial" id="device_lbl_{row_index}_{item_index}">',
                        '{item_name}</span></div>'
                        );
                for(var i = 0; i < search_results.display_rows[row_index][5].length; i ++) {
                  var item_id = search_results.display_rows[row_index][5][i];
                  var checked_status = 'ext-cb-unchecked';
                  // TODO: check performance of this if
                  if(device_search_checked[row_index].indexOf(i) != -1) {
                    checked_status = 'ext-cb-checked';
                  }
                  var item_name = search_results.items[item_id][2];
                  left_col += child_match_row.apply({
                                      row_index: row_index,
                                      item_index: i,
                                      item_id: item_id,
                                      item_name: item_name,
                                      checked_status: checked_status
                                    });
                  right_col += '<div class="device_search_partial_right">';
                  if(search_results.items[item_id][3]) {
                    right_col += search_results.items[item_id][3];
                  }
                  right_col += '</div>';
                }
                row_params.cols = 2;
                row_params.body = '</td><td class="device_search_left_col">' + left_col +
                                  '</td><td class="device_search_right_col">' + right_col;
                return 'x-grid3-row-expanded';
              }
              row_params.cols = 4;
              row_params.body = '';
              return 'x-grid3-row-collapsed';
            }
          }
      });

      device_search_grid.render();
    },

    gridClickHandler: function(e, el) {
      // TODO: break into several methods
      if(!e) { return false; }
      var target_el = e.target || e.srcElement;
      target_el = Ext.get(target_el);

      if(target_el.hasClass('device_search_twizzle')) {
        e.stopEvent();
        MB.createAd.targeting.expandGridRow(target_el.id.substring(22));
      }
      if(target_el.hasClass('device_search_sel_exact')) {
        e.stopEvent();
        var row_index = target_el.id.substring(11);
        if(device_search_checked[row_index].length > 0) {
          device_search_checked[row_index] = [];
          MB.createAd.targeting.toggleCheckbox('device_sel_' + row_index, 0);
        }
        else {
          device_search_checked[row_index] = [0];
          MB.createAd.targeting.toggleCheckbox('device_sel_' + row_index, 1);
        }
      }
      if(target_el.hasClass('device_search_sel_multi')) {
        e.stopEvent();
        var row_index = target_el.id.substring(11);
        var new_setting = 1;
        if(device_search_checked[row_index].length == search_results.display_rows[row_index][5].length) {
          new_setting = 0;
          device_search_checked[row_index] = [];
        }
        else {
          // TODO: clean this up!
          device_search_checked[row_index] = [];
          for(var i = 0; i < search_results.display_rows[row_index][5].length; i ++) {
            device_search_checked[row_index].push(i);
          }
        }
        // mark checkboxes if the row is open
        if(row_index == device_search_expanded_row) {
          for(var i = 0; i < search_results.display_rows[row_index][5].length; i ++) {
              MB.createAd.targeting.toggleCheckbox(
                              Ext.get('device_sel_' + row_index + '_' + i),
                              new_setting
                            );
          }
        }
        MB.createAd.targeting.setParentCheckbox(row_index);
      }
      if(target_el.hasClass('device_search_sel_partial')) {
        e.stopEvent();
        var checkbox_id = target_el.id.substring(11);
        var id_parts = checkbox_id.split('_');
        var item_id = parseInt(id_parts[1], 10);
        var handset_id = search_results.display_rows[id_parts[0]][5][item_id];

        if(device_search_checked[id_parts[0]].indexOf(item_id) != -1) {
          MB.createAd.targeting.toggleCheckbox('device_sel_'+checkbox_id, 0);
          device_search_checked[id_parts[0]].remove(item_id);
        }
        else {
          MB.createAd.targeting.toggleCheckbox('device_sel_'+checkbox_id, 1);
          device_search_checked[id_parts[0]].push(item_id);
        }
        MB.createAd.targeting.setParentCheckbox(id_parts[0]);
      }
    },

    toggleCheckbox: function(element, state) {
      // 0: unchecked, 1: checked,  2: half-checked
      if(state == 0) {
        Ext.get(element).addClass('ext-cb-unchecked');
      }
      else {
        Ext.get(element).removeClass('ext-cb-unchecked');
      }
      if(state == 1) {
        Ext.get(element).addClass('ext-cb-checked');
      }
      else {
        Ext.get(element).removeClass('ext-cb-checked');
      }
      if(state == 2) {
        Ext.get(element).addClass('ext-cb-partial');
      }
      else {
        Ext.get(element).removeClass('ext-cb-partial');
      }
    },

    setParentCheckbox: function(parent_id) {
      if(device_search_checked[parent_id].length == 0) {
        MB.createAd.targeting.toggleCheckbox('device_sel_'+parent_id, 0);
      }
      else if(device_search_checked[parent_id].length == search_results.display_rows[parent_id][5].length) {
        MB.createAd.targeting.toggleCheckbox('device_sel_'+parent_id, 1);
      }
      else {
        MB.createAd.targeting.toggleCheckbox('device_sel_'+parent_id, 2);
      }
    },

    expandGridRow: function(row_index) {
      if(device_search_expanded_row == row_index) {
        device_search_expanded_row = null;
      } else {
        device_search_expanded_row = row_index;
      }

      device_search_grid.getView().refresh();
    },

    hideDevicePopup: function(e,el) {
      if(e) e.stopEvent();
      var target_el = e.target || e.srcElement;

      if(target_el.id == 'device_targeting_popup_addbtn') {
        for(var row_index = 0; row_index < search_results.display_rows.length; row_index ++) {
          if(search_results.display_rows[row_index][5].length == 0) {
            // row with one exact match
            var handset_id = search_results.display_rows[row_index][0];
            if(device_search_checked[row_index].length > 0) {
              targetDevices[handset_id] = search_results.items[handset_id].slice();
            }
          }

          for(var i = 0; i < search_results.display_rows[row_index][5].length; i ++) {
            var handset_id = search_results.display_rows[row_index][5][i];
            if(device_search_checked[row_index].indexOf(i) != -1) {
              targetDevices[handset_id] = search_results.items[handset_id].slice();
            }
          }
        }
      }

      Ext.getBody().unmask();
      Ext.get('device_search_spinner').setDisplayed(false);
      Ext.get('device_targeting_search_button').dom.disabled = false;
      Ext.get('device_targeting_popup').fadeOut();
      MB.createAd.targeting.deviceSearchSampleText(null, 'device_targeting_search');
      MB.createAd.targeting.triggerUpdate();
      MB.createAd.targeting.selectedItemsGrid();
    },

    selectedItemsGrid: function() {
      selected_devices = new Array();
      for(var handset_id in targetDevices) {
        // TODO: clean this up; does selected_devices need scope outside this?
        if(targetDevices.hasOwnProperty(handset_id) && targetDevices[handset_id]) {
          selected_devices.push( [  handset_id,
                                    targetDevices[handset_id][0],
                                    targetDevices[handset_id][1],
                                    targetDevices[handset_id][2],
                                    targetDevices[handset_id][3] ] );
        }
      }

      Ext.get('device_targeting_bysearch_selected_grid').update('');
      if(selected_devices.length < 1) {
        // restore to 'no selected stuff' state; TODO: deuglify
        Ext.get('device_targeting_search').setHeight(120);
        Ext.get('device_targeting_search_desc').setDisplayed(true);
        Ext.get('device_targeting_selected_desc').setDisplayed(false);
        Ext.get('device_targeting_bysearch_selected').setDisplayed(false);
        return false;
      } else {
        Ext.get('device_targeting_search').setHeight(75);
        Ext.get('device_targeting_search_desc').setDisplayed(false);
        Ext.get('device_targeting_selected_desc').setDisplayed(true);
        Ext.get('device_targeting_bysearch_selected').setDisplayed(true);
      }

      var device_selections_datastore = new Ext.data.Store({
            proxy: new Ext.data.MemoryProxy(selected_devices),
            reader: new Ext.data.ArrayReader({}, [
              { name: 'handset_id', type: 'string' },
              { name: 'search_term', type: 'string' },
              { name: 'brand', type: 'string' },
              { name: 'model', type: 'string' },
              { name: 'market_name', type: 'string' }
            ])
      });
      device_selections_datastore.load();
      device_selections_sel_model = new Ext.grid.CheckboxSelectionModel();
      var device_targeting_selections_grid = new Ext.grid.GridPanel({
          el: 'device_targeting_bysearch_selected_grid',
          selModel: device_selections_sel_model,
          width: 398,
          height: 200,
          title: _('Your Targeted Devices'),
          header: false,
          store: device_selections_datastore,
          colModel: new Ext.grid.ColumnModel( [
            device_selections_sel_model,
            { header: _('Brand Name'),
              dataIndex: 'brand',
              width: 105,
              sortable: true,
              menuDisabled: true },
            { header: _('Model Name'),
              dataIndex: 'model',
              width: 132,
              sortable: true,
              menuDisabled: true },
            { header: _('Marketing Name'),
              dataIndex: 'market_name',
              width: 120,
              menuDisabled: true }
          ] )
      });
      device_targeting_selections_grid.render();
    },

    deleteSelectedHandsets: function(e, el) {
      if(e) e.stopEvent();
      var delete_selections = device_selections_sel_model.getSelections();
      if(delete_selections.length != 1 &&
          delete_selections.length == selected_devices.length) {
        if(!confirm(
              _('Are you sure you want to remove all devices from your targeting list?')
            ) ) {
          return false;
        }
      }
      for(var i = 0, item; item = delete_selections[i]; i++) {
        if(targetDevices[item.data.handset_id]) {
          targetDevices[item.data.handset_id] = false;
        }
      }
      // redraw grid
      MB.createAd.targeting.selectedItemsGrid();
    },

    createManufacturerTree: function() {
      if(!manfTree) {
        MB.createAd.state.startManfTree();
        manfTree = MB.createAd.targeting.createTree('manf_targeting_tree',
          { dataUrl: MB.constant.base_control + 'ajax/targeting/manfs/',
            root: _('All Manufacturers'),
            id: 'manufacturers',
            rootAttribute: ['brand', 'any_manf'],
            load: function() {
              if(ad_params && ad_params.targeting) {
                var t = ad_params.targeting;
                if(t.new_manfs.length != 0) {
                  manfTree.getRootNode().getUI().check(0);
                  Ext.each(t.new_manfs, function(item) { manfTree.checkNodeByAttr('brand', item) });
                }
              }
              MB.createAd.state.stopManfTree();
            }
        });
      }
    },

    showCountryTree: function() {
      if(!countryTree) {
        MB.createAd.state.startCountryTree();
        countryTree = MB.createAd.targeting.createTree('countries_targeting_tree',
          { dataUrl: MB.constant.base_control + 'ajax/targeting/countries/',
            root: _('All Countries'),
            id: 'countries',
            rootAttribute: ['c_id', 'any_reg'],
            load: function() {
              if(ad_params && ad_params.targeting) {
                var t = ad_params.targeting;
                if(t.new_regions.length != 0 || t.new_countries.length != 0 || t.new_operators.length != 0) {
                  countryTree.getRootNode().getUI().check(0);
                  Ext.each(t.new_regions, function(item) { countryTree.checkNodeByAttr('c_id', item) });
                  Ext.each(t.new_countries, function(item) { countryTree.checkNodeByAttr('c_id', 'CC'+item) });
                  Ext.each(t.new_operators, function(item) { countryTree.checkNodeByAttr('c_id', item) });
                }
                MB.createAd.state.stopCountryTree();
              }
            }
          });
      }
    },

    createTree: function(div, conf) {
      var tree = new Ext.tree.TreePanel({
          el: div,
          useArrows: true,
          autoScroll: true,
          animate: !Ext.isIE6,
          animCollapse: !Ext.isIE6,
          containerScroll: true,
          height: 250,
          width: 420,
          loader: new Ext.tree.TreeLoader({
            dataUrl: conf.dataUrl,
            listeners: {
              load: conf.load || Ext.emptyFn
            },
            baseAttrs: {
              uiProvider: Ext.tree.TreeCheckNodeUI,
              iconCls: 'n',
              listeners: {
                dblclick : function() {
                  return false;
                },
                checkchange : this.triggerUpdate,
                scope: this
              }
            } //add uiProvider attribute
          })
      });

      // we assume that attr is stored as an array and v is a string
      // this is not generic enough for general use, but fits out needs
      tree.checkNodeByAttr = function(attr, v, startNode) {
        startNode = startNode || this.root;

        var childrenNotRenderedFn = function(n, stack) {
          var as = n[attr];

          if(as && ((typeof as == 'object' && as.indexOf(v) != -1) || as == v)) {
            n.checkedState = 2;
            for(var i = stack.length - 1; i >= 0; i--) {
              var _n = stack[i];
              if(_n.getUI) {
                if(_n.attributes.checkedState < 2) {
                  var checkedChildren = 0;

                  if(_n.attributes.children) {
                    var l = _n.attributes.children.length;
                    for(var k = 0; k < l; k++) {
                      if(_n.attributes.children[k].checkedState == 2) checkedChildren++
                      else break;
                    }
                  } else {
                    var l = _n.childNodes.length;
                    for(var k = 0; k < l; k++) {
                      if(_n.childNodes[k].attributes.checkedState == 2) checkedChildren++
                      else break;
                    }
                  }

                  _n.getUI().check(checkedChildren == l ? 2 : 1);
                }
              }
              else if(_n.checkedState != 2) {
                // check to see if the rest of the children are all checked
                var checkedChildren = 0;
                var l = _n.children.length;
                for(var k = 0; k < l; k++) {
                  if(_n.children[k].checkedState == 2) checkedChildren++
                  else break;
                }
                _n.checkedState = (checkedChildren == l ? 2 : 1);
              }
            }
            // .. and cascade
            var checkChildren = function(node) {
              node.checkedState = 2;
              if(node.children) {
                Ext.each(node.children, checkChildren);
              }
            }
            if(n.children) Ext.each(n.children, checkChildren);
            return false;
          }

          if(n.children) {
            for(var i = 0; i < n.children.length; i++) {
              var new_stack = stack.slice();
              new_stack.push(n);
              if(childrenNotRenderedFn(n.children[i], new_stack) === false) break;
            }
          }
        };

        var childrenRenderedFn = function(n, stack) {
          var as = n.attributes[attr];
          if(as && ((typeof as == 'object' && as.indexOf(v) != -1) || as == v)) {
            n.getUI().check(2);
            n.getUI().parentCheck(n.parentNode, 2); //bubble
            return false;
          }

          if(!n.isLeaf()) {
            if(n.childrenRendered) {
              var cs = n.childNodes;
              for(var i = 0, len = cs.length; i < len; i++) {
                var new_stack = stack.slice();
                new_stack.push(n);
                if(childrenRenderedFn(cs[i], new_stack) === false) break;
              }
            }
            else {
              for(var i = 0; i < n.attributes.children.length; i++) {
                var new_stack = stack.slice();
                new_stack.push(n);
                if(childrenNotRenderedFn(n.attributes.children[i], new_stack) === false) break;
              }
            }
          }
        };

        var cs = startNode.childNodes;
        for(var i = 0, len = cs.length; i < len; i++) {
          var stack = [startNode];
          if(childrenRenderedFn(cs[i], stack) === false) break;
        }
      }; // checkNodeByAttr

      tree.getChecks = function() {
        // TODO: fix this, not DRY, and crappy
        var full = [];
        var partial = [];
        var minimal = [];

        var fullOnly = function(n) {
          if(n.checkedState > 0) {
            // Fully checked
            if(n.checkedState == 2) {
              full.push(n);
            } else if(n.checkedState == 1) {
              partial.push(n);
            }

            if (n.children && n.children.length != 0) {
              Ext.each(n.children, fullOnly, this);
            }
          }
        };

        var fullAndMinimal = function(n) {
          if(n.checkedState > 0) {
            // Fully checked
            if(n.checkedState == 2) {
              full.push(n);
              minimal.push(n);
              if (n.children && n.children.length != 0) {
                Ext.each(n.children, fullOnly, this);
              }
            } else if(n.checkedState == 1) {
              partial.push(n);
              if (n.children && n.children.length != 0) {
                Ext.each(n.children, fullAndMinimal, this);
              }
            }

          }
        };

        if(this.root.attributes.checkedState > 0) {
          if(this.root.attributes.checkedState == 2) {
            full.push(this.root.attributes);
            minimal.push(this.root.attributes);
          } else if(this.root.attributes.checkedState == 1) {
            partial.push(this.root.attributes);
          }

          this.root.eachChild(function(n) {
            if(n.attributes.checkedState > 0) {

              if(n.attributes.checkedState == 2) {
                full.push(n.attributes);

                if(n.parentNode.attributes.checkedState == 1) {
                  minimal.push(n.attributes);
                }
                if(n.attributes.children && n.attributes.children.length != 0) {
                  Ext.each(n.attributes.children, fullOnly, this);
                }
              } else if(n.attributes.checkedState == 1) {
                partial.push(n.attributes);
                if(n.attributes.children && n.attributes.children.length != 0) {
                  Ext.each(n.attributes.children, fullAndMinimal, this);
                }
              }
            }
          });

        }
        return [full, partial, minimal];
      };

      // set the root node
      var rootConf = {
        text: conf.root,
        draggable: false,
        id: conf.id,
        checkedState: 2,
        iconCls: 'n',
        uiProvider: Ext.tree.TreeCheckNodeUI,
        listeners: {
          'dblclick': function() {
            return false;
          }
        }
      };

      if(conf.rootAttribute) rootConf[conf.rootAttribute[0]] = conf.rootAttribute[1];
      var root = new Ext.tree.AsyncTreeNode(rootConf);
      tree.setRootNode(root);

      tree.render();
      root.expand();

      return tree;
    },
    getManfTree: function() { return manfTree; },
    getCountryTree: function() { return countryTree; },

    getValues: function() { // TODO: break apart this method
      var result_obj = { manfs: [],
              countries: [],
              partial_countries: [],
              platform: [],
              cap: [],
              new_cap: [],
              devices: [],
              age: [],
              gender: '',
              minimal_manfs: [],
              minimal_countries: [],
              targeting_package: 'custom',
              msisdn: false };

      // fail if ad details haven't loaded
      if(!MB.createAd.state.getPageReady()) { return result_obj; }

      //------------------------------------------------------------------------
      if(Ext.get('targeting_custom').dom.checked) {
        var countryChecks = countryTree.getChecks();
        Ext.each(countryChecks[0], function(item, i, all) {
          result_obj.countries.push(item.c_id);
        });

        Ext.each(countryChecks[1], function(item, i, all) {
          result_obj.partial_countries.push(item.c_id);
        });

        Ext.each(countryChecks[2], function(item, i, all) {
          result_obj.minimal_countries.push(item.c_id);
        });
      }
      else {
        var country_sel = '';
        Ext.each( Ext.query('#targeting_options input'),
                  function(item) {
                    if(item.checked) {
                      // checkbox IDs are targeting_foo
                      country_sel = item.id.substring(10);
                    }
                  });
        // hack to support additional i18n countries, before
        // we remove bid_obj and thus partial_countries
        var region_map = {'us': 'NA', 'gb': 'EU',
                          'de': 'EU', 'es': 'EU', 'fr': 'EU', 'it': 'EU',
                          'jp': 'AS',
                          'br': 'LA'};

        if(country_sel == 'ron') {
          result_obj.countries = ['any_reg'];
          result_obj.minimal_countries = ['any_reg'];
          result_obj.partial_countries = [];
        }
        else {
          result_obj.countries = ['CC'+country_sel.toUpperCase()];
          result_obj.minimal_countries = ['CC'+country_sel.toUpperCase()];
          result_obj.partial_countries = [region_map[country_sel]];
        }
      }

      //------------------------------------------------------------------------
      if(Ext.get('device_targeting_bymanf').dom.checked) {
        // targeted by manufacturer, platform, and capability
        var manfChecks = manfTree.getChecks();
        Ext.each(manfChecks[0], function(item, i, all) {
          if(item.brand) {
            result_obj.manfs.push(item.brand);
          } else {
            Ext.each(item.children, function(subItem, i, all) {
              result_obj.manfs.push(subItem.brand);
            });
          }
        });
        Ext.each(manfChecks[2], function(item, i, all) {
          if(item.brand) {
            result_obj.minimal_manfs.push(item.brand);
          } else {
            Ext.each(item.children, function(subItem, i, all) {
              result_obj.minimal_manfs.push(subItem.brand);
            });
          }
        });

        if(Ext.get('platform_targeting_specific').dom.checked == true) {
          Ext.each(Ext.query('#platform_targeting_div input'), function(item, i, all) {
            if(item.checked && item.value != 'specific') {
              result_obj.platform.push(item.value);
            }
          });
        }

        if(Ext.get('cap_targeting_specific').dom.checked == true) {
          var cap_checkboxes = Ext.query('#cap_targeting_div input[type=checkbox]');
          // check if all checkboxes are unchecked, default to any_cap
          var cap_checkboxes_checked = [];
          Ext.each(cap_checkboxes, function(item, i, all) {
            if(item.checked) {
              cap_checkboxes_checked.push(item);
            }
          });

          if(cap_checkboxes_checked.length != 0) {
            Ext.each(cap_checkboxes, function(item, i, all) {
              if(!item.checked) {
                result_obj.cap.push(item.value);
              }
              if(item.checked) {
                result_obj.new_cap.push(item.value);
              }
            });
          }
        }
      }
      else if(Ext.get('device_targeting_bysearch').dom.checked) {
        for(var handset_id in targetDevices) {
          if(targetDevices.hasOwnProperty(handset_id) && targetDevices[handset_id]) {
            // server will check this is a valid targeting string
            result_obj.devices.push(handset_id);
          }
        }
      }

      if(result_obj.devices.length < 1) {
        result_obj.devices = ['any_dev'];
      }
      if(result_obj.manfs.length < 1) {
        result_obj.manfs = ['any_manf'];
      }
      if(result_obj.minimal_manfs.length < 1) {
        result_obj.minimal_manfs = ['any_manf'];
      }
      if(result_obj.platform.length < 1) {
        result_obj.platform = ['any_plat'];
      }
      if(result_obj.cap.length < 1) {
        result_obj.cap = ['any_cap'];
      }
      if(result_obj.new_cap.length < 1) {
        result_obj.new_cap = ['any_cap'];
      }

      //------------------------------------------------------------------------
      if(!Ext.get('gender_targeting_all') || Ext.get('gender_targeting_all').dom.checked) {
        result_obj.gender = 'any_gender';
      }
      else {
        if(Ext.get('gender_targeting_female').dom.checked) {
          result_obj.gender = 'female';
        }
        else {
          result_obj.gender = 'male';
        }
      }

      //------------------------------------------------------------------------
      if(Ext.get('age_targeting_specific') && Ext.get('age_targeting_specific').dom.checked) {
        var age_checkboxes = Ext.query('#age_targeting_div input[type=checkbox]');
        var age_checkboxes_checked = [];
        Ext.each(age_checkboxes, function(item, i, all) {
          if(item.checked) {
            age_checkboxes_checked.push(item);
          }
        });

        if(age_checkboxes_checked.length != 0) {
          Ext.each(age_checkboxes, function(item, i, all) {
            if(item.checked) {
              result_obj.age.push(item.value);
            }
          });
        }
      }

      if(result_obj.age.length < 1) {
        result_obj.age = ['any_age'];
      }

      //------------------------------------------------------------------------
      if(Ext.get('msisdn_targeting')) {
        result_obj.msisdn = Ext.get('msisdn_on').dom.checked;
      }

      return result_obj;
    },

    getReview: function() {
      var r = MB.createAd.targeting.getValues();
      r.real_countries = [];
      r.real_regions = [];
      r.real_carriers = [];
      if( !Ext.get('targeting_custom').dom.checked &&
          !Ext.get('targeting_custom').dom.checked) {
        Ext.each( Ext.query('#targeting_options input'),
            function(item) {
              if(item.checked) {
                // hack! this relies on checkboxes being followed by a label
                r.real_countries = [Ext.get(Ext.get(item).next('label')).dom.innerHTML];
              }
            });
      }
      if(Ext.get('targeting_custom').dom.checked && countryTree) {
        var country_checks = countryTree.getChecks();
        Ext.each(country_checks[0], function(item, i, all) {
          if(item.c_id == 'any_reg') { return false; }
          if(item.c_id[0].length == 2) r.real_regions.push(item.text);
          else if(item.c_id[0].match(/^CC..$/)) r.real_countries.push(item.text);
          else r.real_carriers.push(item.text);
        });

        Ext.each(country_checks[1], function(item, i, all) {
          if(item.c_id != 'any_reg') {
            if(item.c_id[0].length == 2) r.real_regions.push(_(item.text) + "&nbsp;(" + _("partial") + ")");
            else if(item.c_id[0].match(/^CC..$/)) r.real_countries.push(_(item.text) + "&nbsp;(" + _("partial") + ")");
          }
        });
      }

      Ext.get('review_targeting').update(targetingTpl(r)).highlight();
      currentReviewArray = r;
    },

    showDetails: function() {
      if(!targetingDetailsDialogTpl) {
        targetingDetailsDialogTpl = new Ext.XTemplate(
          '<div class="column">',
          '<div class="header">', _('Regions'), '</div><ul><tpl if="this.is_any(countries)"><li class="all">', _('All Regions'), '</li></tpl><tpl if="this.e(real_regions)">{[this.list(values["real_regions"])]}</tpl></ul>',
          '<tpl if="this.has_items(devices)"></div><div class="column"></tpl>',
          '<div class="header">', _('Countries'), '</div><ul><tpl if="this.is_any(countries)"><li class="all">', _('All Countries'), '</li></tpl><tpl if="this.e(real_countries)">{[this.list(values["real_countries"])]}</tpl></ul>',
          '</div>',
          '<div class="column"><div class="header">', _('Carriers'), '</div><ul><tpl if="this.is_any(countries)"><li class="all">', _('All Carriers'), '</li></tpl><tpl if="this.e(real_carriers)">{[this.list(values["real_carriers"])]}</tpl></ul></div>',
          '<tpl if="this.has_items(devices)"><div class="column">',
          '<div class="header">', _('Devices'), '</div><ul><tpl if="this.is_any(devices)"><li class="all">', _('All Devices'), '</ul></tpl><tpl if="this.e(devices)">{[this.list(values["devices"])]}</tpl></ul>',
          '</div></tpl>',
          '<tpl if="this.is_any(devices)"><div class="column">',
          '<div class="header">', _('Manufacturers'), '</div><ul><tpl if="this.is_any(manfs)"><li class="all">', _('All Manufacturers'), '</li></tpl><tpl if="this.e(manfs)">{[this.list(values["manfs"])]}</tpl></ul>',
          '</div><div class="column">',
          '<div class="header">', _('Required Capabilities'), '</div><ul><tpl if="this.is_any(new_cap)"><li class="all">', _('Any Capabilities'), '</ul></tpl><tpl if="this.e(new_cap)">{[this.list(values["new_cap"])]}</tpl></ul>',
          '<div class="header">', _('Platforms'), '</div><ul><tpl if="this.is_any(platform)"><li class="all">', _('All Platforms'), '</ul></tpl><tpl if="this.e(platform)">{[this.list(values["platform"])]}</tpl></ul>',
          '</div></tpl>',
          '</div>',
          {
            e: function(a) {
              return a.length != 0;
            },
            has_items: function(a) {
              return a.length > 1;
            },
            is_any: function(a) {
              if(a.length == 1 && typeof a[0] == 'string' && a[0].substring(0,4) == 'any_') {
                return true;
              } else {
                return false;
              }
            },
            list: function(a) {
              var r = '';
              for(var i = 0, l = a.length; i < l; i++) {
                // replace carets in handset target IDs, skip 'any'
                // TODO: clean this up? manfs are one-item arrays
                if(typeof a[i] == 'string') {
                  if(a[i].substring(0,4) == 'any_') { continue; }
                  a[i] = a[i].replace(/\^/g,' ');
                }
                r += '<li>' + _(a[i]) + '</li>';
              }
              return r;
            }
          }
        );
      }

      if(!currentReviewArray.sorted) {
        for(var k in currentReviewArray) {
          if(currentReviewArray[k].sort) {
            currentReviewArray[k] = currentReviewArray[k].sort();
          }
        }
        currentReviewArray.sorted = true;
      }

      var str = targetingDetailsDialogTpl.apply(currentReviewArray);

      Ext.get('targetingDetailsDialogContent').update(str);

      var targetingDetailsDialog = new Ext.Window({
        floating: true,
        shim: true,
        draggable: false,
        header: false,
        modal: true,
        resizable: false,
        width: 725,
        height: 525,
        bodyCfg: { tag:'center' },
        buttons: [{
          text: _('OK'),
          menuAlign: 'r-l',
          listeners: {
            click: function(b) {
              b.ownerCt.hide();
            }
          }
        }],
        title: _('Targeting Details'),
        body: Ext.get('targetingDetailsDialogContent'),
        closeAction: 'hide'
      });
      Ext.get('targetingDetailsDialogContent').show();
      targetingDetailsDialog.show();
      return false;
    },

    triggerUpdate: function() {
      Ext.select('span[id*=c_]', true, 'all_channels').update('-');
      Ext.get('review_targeting').update('-');
      Ext.get('c_min_bid_all').update('-');
      Ext.get('c_high_bid_all').update('<img src="' + MB.constant.base_url + 'img/spinner-anim.gif" />');

      if(bidGuideUpdateCall) window.clearTimeout(bidGuideUpdateCall);
      bidGuideUpdateCall = this.updateBidGuide.defer(1500, this);
    },

    updateBidGuide: function() {
      var values = this.getValues();

      // abort mission! targeting tree is invalid anyway
      if(values.countries.length == 0 ||
          (values.devices.length == 0 &&
          (values.manfs.length == 0 || values.platform.length == 0 || values.new_cap.length == 0)
          ) ) {
        Ext.get('c_min_bid_all').update('-');
        Ext.get('c_high_bid_all').update('-');
        Ext.get('review_targeting').update('-');
      }
      else {
        Ext.Ajax.abort(bidGuideUpdateAjaxCall);
        bidGuideUpdateAjaxCall = Ext.Ajax.request({
          url: MB.constant.base_control + 'ajax/targeting/get_bid_guides',
          success: function(r) {
            var all_min = 0, all_max = 0, count = 0;
            var guide = Ext.decode(r.responseText);

            for(var i in guide) {
              Ext.get('c_min_bid_' + (i)).update(MB.format(guide[i][0])).highlight();
              Ext.get('c_high_bid_' + (i)).update(MB.format(guide[i][2])).highlight();
              all_min += guide[i][0];
              all_max += guide[i][2];
              count++;
            }
            Ext.get('c_min_bid_all').update(MB.format(all_min / count)).highlight();
            Ext.get('c_high_bid_all').update(MB.format(all_max / count)).highlight();
            if(!MB.createAd.channels.isAllInputDirty()) {
              var suggested_bid = MB.createAd.targeting.isRon() ? (all_min / count) + 0.01 : (all_max / count) + 0.01;
              Ext.get('all_channel_text_bid').dom.value = MB.format(suggested_bid, {grp_sep: ''});
            }
            if(!MB.createAd.channels.isImagePremiumDirty()) {
              Ext.get('image_bid').dom.value = MB.format(Math.round(20 * all_min / count) / 100, {grp_sep: ''});
            }
            MB.createAd.minPremium = Math.round(20 * all_min / count) / 100;
            MB.createAd.channels.getReview();
          },
          failure: function(r) {
            this.updateBidGuide.defer(2000, this); // retry in 2 seconds
          },
          scope: this,
          method: 'POST',
          params: {d: Ext.encode(values)}
        });
        this.getReview();
      }
    },
    isRon: function() {
      return Ext.get('targeting_ron').dom.checked == true;
    }
  };
}();

MB.createAd.preview = function() {
  var tabs;
  var panels;
  var adTextInput;
  var linkInput;
  var links;
  var currentTextValue;
  var currentLinkValue;

  return {
    init: function() {
      tabs = Ext.query('#preview .thirdNavTabs ul li a');
      panels = Ext.query('#preview .preview_content');
      adTextInput = Ext.get('ad_text');
      linkInput = Ext.get('destinationUrl');
      links = Ext.query('.preview_content a');

      currentTextValue = '';
      currentLinkValue = '';

      for (var i = 0; i < tabs.length; i++) {
        var tab = Ext.get(tabs[i]);
        var panel = Ext.get(panels[i]);
        tab.on('click', this.linkClicked, {'tab': tab, 'panel':panel}, {'stopEvent' : true});
      }

      /* Declare and start the listener task to update the ad preview */
      var task = {
        run: function() {
          var textValue = adTextInput.getValue();
          var linkValue;
          if (Ext.get('link_url_lp').dom.checked == true && Ext.get('landingPage')) {
            linkValue = lp_base + Ext.get('landingPage').getValue();
          } else {
            linkValue = linkInput.getValue();
          }


          var updateText = currentTextValue != textValue;
          var updateLink = currentLinkValue != linkValue;

          for(var i = 0; (updateText || updateLink) && i < links.length; i++) {
            if (updateText) {
              currentTextValue = textValue;
              textValue = textValue.replace('%phn%', 'i600').replace('%man%', 'Samsung').replace('%opr%', 'Verizon');
              Ext.get(links[i]).update(textValue);
              Ext.get('review_ad_text').update(textValue);
              currentTextValue = textValue;
            }
            if (updateLink) {
              Ext.get(links[i]).dom.href = linkValue;
              currentLinkValue = linkValue;
            }
          }
        },
        interval: 500,
        scope: this
      };
      new Ext.util.TaskRunner().start(task);
      new MB.TextInputLabeler(_('Click here to enter ad text'), 'ad_text');
      new MB.TextInputLabeler(_('Click here to enter an ad name'), 'ad_name');
    },

    linkClicked: function() {
      Ext.get(Ext.query('#preview .thirdNavTabs ul li a.current')[0]).toggleClass('current');
      Ext.get(Ext.query('#preview .selected')[0]).toggleClass('selected');
      this['tab'].toggleClass('current');
      this['panel'].toggleClass('selected');
      if(this['tab'].blur)this['tab'].blur();
    },

    getValues: function() {
    }
  };
}();

MB.createAd.adText = function() {
  return {
    init: function() {
      // Edit mode!
      if (ad_params) {
        Ext.get('ad_name').dom.value = ad_params['ad_name'];
        Ext.get('ad_text').dom.value = ad_params['ad_text'];
        if(ad_params['lp']) {
          Ext.get('link_url_lp').dom.checked = true;
          for(var i = 0; i < Ext.get('landingPage').dom.options.length; i++) {
            if (Ext.get('landingPage').dom.options[i].value == ad_params['lp']) {
              Ext.get('landingPage').dom.options[i].selected = true;
              break;
            }
          }
        } else {
          Ext.get('destinationUrl').dom.value = ad_params['ad_url'];
          Ext.get('link_url_existing').dom.checked = true;
        }
      }

      Ext.get('link_url_existing_div').setVisibilityMode(Ext.Element.DISPLAY);
      Ext.get('link_url_existing').on('click', this.selectExisting);

      Ext.get('link_url_lp_div').setVisibilityMode(Ext.Element.DISPLAY);
      Ext.get('link_url_lp').on('click', this.selectLandingPages);

      if(Ext.get('link_url_lp').dom.checked) this.selectLandingPages();
      else this.selectExisting();
    },
    getValues: function() {
      var ad_text_obj = {
        ad_name: Ext.get('ad_name').getValue(),
        ad_text: Ext.get('ad_text').getValue(),
        link_to: 'existing',
        landing_page: null,
        ad_url: Ext.get('destinationUrl').dom.value
      };
      if(Ext.get('link_url_lp').dom.checked && Ext.get('landingPage')) {
        ad_text_obj.landing_page = Ext.get('landingPage').getValue();
        ad_text_obj.link_to = 'lp';
      }
      return ad_text_obj;
    },
    selectExisting: function(e, el) {
      if(!e) Ext.get('link_url_existing').dom.checked = true;
      Ext.get('link_url_lp_div').hide();
      Ext.get('link_url_existing_div').show();
    },
    selectLandingPages: function(e, el) {
      Ext.get('link_url_lp_div').show();
      Ext.get('link_url_existing_div').hide();
    }
  };
}();

MB.createAd.images = function() {
  var uploadForm = null;

  var expanderClick = function(e, el) {
    if(Ext.get(el).hasClass('expanded')) {
      Ext.get('imageDetails').slideOut('t', {useDisplay: true, callback: function() { Ext.get('imagesSummary').setDisplayed(true)}});
    } else {
      Ext.get('imagesSummary').setDisplayed('none');
      Ext.get('imageDetails').slideIn('t', {useDisplay: true});
    }
    Ext.get(el).toggleClass('expanded');
    Ext.get(el).toggleClass('collapsed');
  };

  return {
    init: function() {
      uploadForm = Ext.get('uploadForm');

      uploadForm.on('submit', this.uploadImage, null, {'stopEvent' : true});

      Ext.get('imageExpander').on('click', expanderClick, null, {'stopEvent' : true});

      var deleteLinks = Ext.query('.delete');
      for (var i = 0; i < deleteLinks.length; i++) {
        Ext.get(deleteLinks[i]).on('click', this.deleteImage, Ext.get(deleteLinks[i]), {'stopEvent' : true});
      }

      var copyImages = Ext.query('.copySection a');
      for (var i = 0; i < copyImages.length; i++) {
        Ext.get(copyImages[i]).on('click', this.copyImage);
      }

      //Edit mode
      if(ad_params && ad_params.banner_urls) {
        for (var i = 0; i < ad_params['banner_urls'].length; i++) {
          var size = ad_params['banner_urls'][i][0];
          var relativeUrl = ad_params['banner_urls'][i][1];
          var fullUrl = ad_params['media_base'] + relativeUrl;

          MB.createAd.images.updateDomWithImage(size, fullUrl, relativeUrl);
        }

      }

      this.setTitle();
    },

    uploadImage: function() {
      if (Ext.get('image').getValue() != '') {

        Ext.get('imageSections').mask(_('Loading ...') + ' <img align="absmiddle" src="' + MB.constant.base_url + '/img/spinner-anim.gif"/>');
        Ext.get('upload').dom.disabled = true;

        Ext.Ajax.request({
          form: uploadForm,
          method: 'POST',
          timeout: 60000,
          isUpload: true,

          success:
            function(connection, response, options)
            {
              try {
                var result = Ext.util.JSON.decode(connection.responseText);
              } catch (err) {
                var result = {'errorText': _('Error occurred in uploading image.')};
              }

              if (result['success']) {
                var fullUrl = result['fullUrl'];
                var relativeUrl = result['relativeUrl'];
                var size = result['size'];
                MB.createAd.images.updateDomWithImage(size, fullUrl, relativeUrl);

                Ext.get('imageErrorContainer').slideOut('t', {useDisplay: true});
                Ext.get('fileInput').update("<input type='file' name='image' id='image'>");
                MB.createAd.images.setTitle();
                MB.createAd.images.dismissModal();
              } else {
                MB.createAd.images.dismissModal();
                Ext.get('imageError').update(result['errorText']);
                Ext.get('imageErrorContainer').slideIn('t', {useDisplay: true});
              }
            },
          failure:
            function(response, options)
            {
                MB.createAd.images.dismissModal();
                Ext.get('imageError').update(result['errorText']);
                Ext.get('imageErrorContainer').slideIn('t', {useDisplay: true});
            }
        });
      }
    },

    copyImage: function() {
      var size = this.id.split("_")[0];
      var direction = this.id.split("_")[1];
      var file = Ext.get(size + "_image_url").getValue();
      if(file != '') {
        Ext.get('imageSections').mask(_('Loading ...') + ' <img align="absmiddle" src="' + MB.constant.base_url + '/img/spinner-anim.gif"/>');
        Ext.get('upload').dom.disabled = true;

        Ext.Ajax.request({
          method: 'POST',
          timeout: 60000,
          url: MB.constant.base_control + 'my_ads/upload_image/process_upload/',
          params: {'size': size, 'direction': direction, 'file': file},
          success:
            function(connection, response, options)
            {
              try {
                var result = Ext.util.JSON.decode(connection.responseText);
              } catch (err) {
                var result = {'errorText': _('Error occurred in copying image.')};
              }
              if (result['success']) {
                var fullUrl = result['fullUrl'];
                var relativeUrl = result['relativeUrl'];
                var size = result['size'];
                MB.createAd.images.updateDomWithImage(size, fullUrl, relativeUrl);

                Ext.get('imageErrorContainer').slideOut('t', {useDisplay: true});
                Ext.get('fileInput').update("<input type='file' name='image' id='image'>");
                MB.createAd.images.dismissModal();
                Ext.get('imageErrorContainer').slideOut('t', {useDisplay: true});
                MB.createAd.images.setTitle();
              } else {
                MB.createAd.images.dismissModal();
                Ext.get('imageError').update(result['errorText']).setDisplayed('block');
                Ext.get('imageErrorContainer').slideIn('t', {useDisplay: true});
              }
            },
          failure:
            function(response, options)
            {
              MB.createAd.images.dismissModal();
              Ext.get('imageError').update(result['errorText']);
              Ext.get('imageErrorContainer').slideIn('t', {useDisplay: true});
            }
        });
      }
    },
    updateDomWithImage: function(size, fullUrl, relativeUrl) {
      switch(size) {
        case 200:
        case 210:
        case 220:
          Ext.get('s_img').dom.src = fullUrl;
          Ext.get('s_image_url').dom.value = relativeUrl;
          Ext.query('#content_s img')[0].src = fullUrl;
          Ext.get('s_element_img').dom.src = fullUrl;
          Ext.get(Ext.query('#content_s img')[0]).setDisplayed('block');
          break;
        case 201:
        case 211:
        case 221:
          Ext.get('m_img').dom.src = fullUrl;
          Ext.get('m_image_url').dom.value = relativeUrl;
          Ext.query('#content_m img')[0].src = fullUrl;
          Ext.get('m_element_img').dom.src = fullUrl;
          Ext.get(Ext.query('#content_m img')[0]).setDisplayed('block');
          break;
        case 202:
        case 212:
        case 222:
          Ext.get('l_img').dom.src = fullUrl;
          Ext.get('l_image_url').dom.value = relativeUrl;
          Ext.query('#content_l img')[0].src = fullUrl;
          Ext.get('l_element_img').dom.src = fullUrl;
          Ext.get(Ext.query('#content_l img')[0]).setDisplayed('block');
          break;
        case 203:
        case 213:
        case 223:
          Ext.get('xl_img').dom.src = fullUrl;
          Ext.get('xl_image_url').dom.value = relativeUrl;
          Ext.query('#content_xl img')[0].src = fullUrl;
          Ext.get('xl_element_img').dom.src = fullUrl;
          Ext.get(Ext.query('#content_xl img')[0]).setDisplayed('block');
          break;
      }
    },
    setTitle: function() {
      var imageSet = false;
      var imageInputs = Ext.query('.image_url');
      for (var i = 0; i < imageInputs.length; i++) {
        if (Ext.get(imageInputs[i]).getValue() != '') {
          imageSet = true;
          break;
        }
      }

      if (imageSet) {
        Ext.get('review_creatives').update(_('Text & Image'));
        Ext.each(Ext.query('.imageRequiredForDisplay'), function(obj) { Ext.get(obj).setDisplayed(true) });
        Ext.get(Ext.query('body')[0]).addClass('imageLoaded');
      } else {
        Ext.get('review_creatives').update(_('Text'));
        Ext.each(Ext.query('.imageRequiredForDisplay'), function(obj) { Ext.get(obj).setDisplayed('none') });
        Ext.get(Ext.query('body')[0]).removeClass('imageLoaded');
      }

    },
    dismissModal: function() {
      Ext.get('imageSections').unmask();
      Ext.get('upload').dom.disabled = false;
    },
    deleteImage: function() {
      var size = this.id.split('_')[0];
      Ext.get(size + '_img').dom.src = MB.constant.base_url + 'img/bg-grayfade.gif';
      Ext.get(size + '_element_img').dom.src = MB.constant.base_url + 'img/bg-grayfade.gif';
      Ext.get(size + '_image_url').dom.value = '';

      Ext.query('#content_' + size + ' img')[0].src = MB.constant.base_url + 'img/bg-grayfade.gif';
      Ext.get(Ext.query('#content_' + size + ' img')[0]).setDisplayed(false);
      MB.createAd.images.setTitle();
    },
    getValues: function() {
      var data = {};
      Ext.each(['s', 'm', 'l', 'xl'], function(item) {
        if (Ext.get(item + '_image_url').getValue() != '') {
          data[item + '_image_url'] = Ext.get(item + '_image_url').getValue();
        }
      }, this);
      return {images: data};
    }
  };
}();

MB.createAd.submit = function() {
  var highBid = null;
  var data = null;

  return {
    init: function() {
      Ext.get('create_ad_submit').on('click', this.preSubmit, this);

      var startOverDialog = new Ext.Window({
        draggable: false,
        header: false,
        modal: true,
        resizable: false,
        width: 300,
        height: 125,
        buttons: [{
          text: (ad_params && ad_params.edit_mode) ? _('Yes') : _('Start Over'),
          listeners: {
            click: function(b) {
              if(ad_params && ad_params.edit_mode) {
                document.location = MB.constant.base_control + 'my_ads/';
              }
              else {
                document.location = MB.constant.base_control + 'my_ads/create_ad/';
              }
            }
          }
        },{
          text: (ad_params && ad_params.edit_mode) ? _('No') : _('Cancel'),
          listeners: {
            click: function(b) {
              b.ownerCt.hide();
            }
          }
        }],
        title: (ad_params && ad_params.edit_mode) ? _('Cancel?') : _('Start Over?'),
        body: Ext.get('startOverContent'),
        closeAction: 'hide'
      });

      Ext.get('create_ad_start_over').on('click', function() { Ext.get('startOverContent').show(); startOverDialog.show(); });
    },
    preSubmit: function(e, el) {
      el.disabled = true;
      var min_bid = parseFloat(Ext.get('c_min_bid_all').dom.innerHTML);
      data = this.gather();
      if(!isNaN(min_bid) && MB.createAd.targeting.isRon()) {
        var show_dialog = false;
        var bids = MB.createAd.channels.getValues();
        if(bids.all_channels_bid && bids.all_channels_bid > (2 * min_bid)) {
          show_dialog = true;
        }
        else {
          for(var i in bids.channels) {
            if(bids.channels[i] > (2 * min_bid)) {
              show_dialog = true;
            }
          }
        }
      }
      if(ad_params && ad_params.targeting &&
          ( ad_params.targeting.new_regions.length != 0 ||
            ad_params.targeting.new_operators.length != 0 ||
            ad_params.targeting.new_countries.length != 0 )
          && data.minimal_countries.length == 1
          && data.minimal_countries[0] == 'any_reg' ) {
        // user has removed country targeting
        show_dialog = true;
      }
      if(show_dialog) {
        if(!highBid) {
          highBid = new Ext.Window({
            draggable: false,
            header: false,
            modal: true,
            resizable: false,
            width: 325,
            height: 175,
            buttons: [{
                text: _('Yes'),
                listeners: {
                  click: function(b) {
                    b.ownerCt.hide();
                    this.submit(el, e);
                  },
                  scope: this
                }
              },{
                text: _('No'),
                listeners: {
                  click: function(b) {
                    el.disabled = false;
                    b.ownerCt.hide();
                  }
                }
              }],
            title: _('Confirm RON Targeting and Bid'),
            body: Ext.get('highBidWarn'),
            closeAction: 'hide'
          });
          Ext.get('highBidWarn').show();
        }
        highBid.show();
        return;
      }
      this.submit(e, el);
    },
    submit: function(e, el) {
      Ext.get('create_ad_start_over').dom.disabled = true;
      Ext.get('submit_spinner').show();
      // First we'll remove all of the error markigns & error messages.
      Ext.select('.wrong').toggleClass('wrong');
      Ext.get('error').setDisplayed('none');
      Ext.get('errorList').update('');

      if(ad_params && ad_params.edit_mode) {
        data.ad_id = ad_params.ad_id;
      }

      Ext.Ajax.request({
        url: MB.constant.base_control + 'my_ads/create_ad_ajax/create',
        method: 'POST',
        timeout: 90000,
        params: {d: Ext.encode(data)},
        success: function(r) {
          var response = Ext.decode(r.responseText);
          if(response['success'] == false) {
            for(var key in response['errors']) {
              Ext.get(key).addClass('wrong');
              if (response['errors'][key].length > 0) {
                Ext.DomHelper.append('errorList', {tag: 'li', html: response['errors'][key]});
              }
              Ext.get('error').setDisplayed('block');
            }
            Ext.get('submit_spinner').hide();
            scroll(0,0);
            el.disabled = false;
            Ext.get('create_ad_start_over').dom.disabled = false;
          } else {
            window.location = response['url'];
          }
        },
        failure: function(r) {
          el.disabled = false;
          Ext.get('create_ad_start_over').dom.disabled = false;
          Ext.get('submit_spinner').hide();
          alert(_('There was an issue creating your ad. Please try again.'));
        }
      });
    },
    gather: function() {
      var data = {};
      Ext.each(MB.createAd.modules, function(item) {
        var foo = MB.createAd[item].getValues();
        if(foo) {
          for(var i in foo) {
            data[i] = foo[i];
          }
        }
      }, this);

      return data;
    },
    getValues: function() {
    }
  };
}();


MB.createAd.copy = function() {
  return {
    init: function() {
      var at = Ext.fly('adTemplate');
      if(at) {
        at.on({
          mousedown: function() {
            Ext.get('adSourceExisting').dom.checked = true;
          },
          change: function(e, el) {
            if(el.value != '')
              document.location = MB.constant.base_control + '/my_ads/create_ad/?copy=' + el.value;
          }
        });
      }
      var create_new = Ext.fly('adSourceBlank');
      if(create_new) {
      	create_new.on('click', function(e, el) {
          if(document.location.toString().match(/\?copy=/))
            document.location = MB.constant.base_control + '/my_ads/create_ad/';
      	});
      }

    },
    getValues: function() {
      return {};
    }
  };
}();


MB.createAd.state = function() {
  var page_ready = false;
  var country_animation = false;
  var device_animation = false;
  var specific_animation = false;
  var bid_guides = false;
  var load_steps = {
    // trees aren't inited by default
    country_tree: false,
    manf_tree: false,
    checkboxes: true
  }

  return {
    init: function() {
    },

    startCountry: function() {
      if(country_animation) {
        // let the current animation finish
        return false;
      }
      else {
        country_animation = true;
        return true;
      }
    },
    stopCountry: function() {
      country_animation = false;
    },
    startDevice: function() {
      if(device_animation) {
        return false;
      }
      else {
        device_animation = true;
        return true;
      }
    },
    stopDevice: function() {
      device_animation = false;
    },
    startSpecific: function() {
      if(specific_animation) {
        return false;
      }
      else {
        specific_animation = true;
        return true;
      }
    },
    stopSpecific: function() {
      specific_animation = false;
    },

    startCountryTree: function() {
      load_steps.country_tree = true;
    },
    stopCountryTree: function() {
      load_steps.country_tree = false;
      MB.createAd.state.loadStepFinished();
    },
    startManfTree: function() {
      load_steps.manf_tree = true;
    },
    stopManfTree: function() {
      load_steps.manf_tree = false;
      MB.createAd.state.loadStepFinished();
    },
    startCheckboxes: function() {
      load_steps.checkboxes = true;
    },
    stopCheckboxes: function() {
      load_steps.checkboxes = false;
      MB.createAd.state.loadStepFinished();
    },

    loadStepFinished: function() {
      if(!page_ready) {
        for(var i in load_steps) {
          if(load_steps[i]) { return false; }
        }
        // hide submit button spinner and update bid guides
        Ext.get('submit_spinner').hide();
        Ext.get('create_ad_submit').dom.disabled = false;
        MB.createAd.targeting.triggerUpdate();
        page_ready = true;
      }
    },
    getPageReady: function() {
      return page_ready;
    },
    getValues: function() {
      return {};
    }
  };
}();


MB.onReady(function() {
  if(Ext.get('grandfatherContent')) {
    var grandfatherDialog = new Ext.Window({
      draggable: false,
      header: false,
      modal: true,
      resizable: false,
      width: 325,
      height: 175,
      buttons: [{
          text: _('OK'),
          listeners: {
            click: function(b) {
              b.ownerCt.hide();
            }
          }
        },{
          text: _('Cancel'),
          listeners: {
            click: function(b) {
              document.location = MB.constant.base_control + 'my_ads/';
            }
          }
        }],
      title: _('New Minimum Bids'),
      body: Ext.get('grandfatherContent'),
      closeAction: 'hide'
    });
    Ext.get('grandfatherContent').show();
    grandfatherDialog.show();
  }

  Ext.each(MB.createAd.modules, function(item) {
    MB.createAd[item].init.defer(10, MB.createAd[item]);
  });
});

